package com.foton.bpc.all.remoting.netty.codec.impl;

import com.foton.bpc.all.remoting.dto.BpcInvacation;
import com.foton.bpc.all.remoting.netty.codec.Codec;
import com.foton.bpc.all.serialzation.Serialzation;
import com.foton.bpc.all.serialzation.json.JsonSerialzation;
import com.foton.bpc.all.util.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author RenPu
 * @Date 2023/6/6 16:15
 * @Version 1.0
 * @Description: 编解码器得实现类
 **/
@Slf4j
public class BpcCodec implements Codec {
    private Class<?> decodeType;
    
    private Serialzation serialzation;
    
    //定义协议得头部
    private final  static byte[] MAGIC=new byte[]{(byte) 0xda,(byte) 0xbb};
    //定义协议头部长度
    private final static int HEAD_LENGTH=6;

    //定义临时存储得buf对象
    ByteBuf tempSpace=Unpooled.buffer();


    /**
     *  编码- java Object——————》byte[]  [客户端]
     * @param msg
     * @return
     * @throws Exception
     */
    @Override
    public byte[] encode(Object msg) throws Exception {
        byte[] result=(byte[])msg;
        return result;
    }



    /**
     *  解码- byte[]——————》Java Object  [服务端]
     * @param data
     * @return
     * @throws Exception
     */
    @Override
    public List<Object> decode(byte[] data) throws Exception {


        /**
         *
         * 请求数据格式：
         *   请求头部关键字（2字节）    业务数据长度（4字节）          业务数据
         *   0xdabb                      4INT                  BpcInvacation 对象序列化
         *
         */



        List<Object> out = new ArrayList<>();
        ByteBuf message = Unpooled.buffer();
        int tempSpaceLen = tempSpace.readableBytes();

            //1：校验临时存储空间是否有暂存数据
            //2:如果有得话则进行数据得合并，反之直接将数据写入到buf对象种
            if (tempSpaceLen > 0) {
                message.writeBytes(tempSpace);
                message.writeBytes(data);
                log.info("合并：上一数据包，余下的长度为："+tempSpaceLen+"合并后的长度为："+message.readableBytes());
            }else {
                message.writeBytes(data);
            }

//        //3:验证数据内容是否小于协议投长度
//        for (;;) {
//            if(HEAD_LENGTH>=message.readableBytes()){
//               tempSpace.clear();
//               tempSpace.writeBytes(message);
//                return out;
//            }
//
//
//            //4：协议头得得校验是否符合
//
//            /**
//             * 数据格式
//             *请求头（2字节） 业务数据长度（4字节） 业务数据（8字节）
//             */
//
//
//            /**
//             * 根据数据格式长度，所以采用的初始化为2字节
//             * 初始化，二个字节的进行匹配，如果还没匹配上（数据未读完），每次进行向后匹配一个
//             * 数据要是读完了，还未发现正确的头，则直接进行数据暂存，等下一次数据
//             */
//            byte[] index = new byte[2];
//            message.readBytes(index);
//            for (;;) {
//                if(index[0]!=MAGIC[0]||index[1]!=MAGIC[1]){
//                    if(message.readableBytes()==0){
//                        tempSpace.clear();
//                        tempSpace.writeByte(index[1]);
//                        return out;
//                    }
//                    index[0]=index[1];
//                    index[1]=message.readByte();
//                }else {
//                    break;
//                }
//            }
//
//            //5：验证数据得缺失，是否进行暂存
//            byte[] lengthBytes = new byte[4];
//            message.writeBytes(lengthBytes);
//            int len = ByteUtils.Byte2Int(lengthBytes);
//
//            //读取body，还没传输完成，暂存下，先不处理
//            if(message.readableBytes()<len){
//                tempSpace.clear();
//                tempSpace.writeBytes(index);
//                tempSpace.writeBytes(lengthBytes);
//                tempSpace.writeBytes(message);
//                return out;
//            }


            //6：序列为java对象，存储到集合
            byte[] body = new byte[message.readableBytes()];
            message.readBytes(body);
            Object o = getSerialzation().derialzation(body, decodeType);
            out.add(o);
            return out;
        //}
    }



    /**
     *
     * @return
     * @throws Exception
     */
    @Override
    public Codec creteInstance() throws Exception {
        BpcCodec bpcCodec = new BpcCodec();
        bpcCodec.setDecodeType(BpcInvacation.class);
        bpcCodec.setSerialzation(new JsonSerialzation());
        return   bpcCodec;
    }




    public Serialzation getSerialzation() {
        return serialzation;
    }

    public void setSerialzation(Serialzation serialzation) {
        this.serialzation = serialzation;
    }


    public Class<?> getDecodeType() {
        return decodeType;
    }

    public void setDecodeType(Class<?> decodeType) {
        this.decodeType = decodeType;
    }

}
